import os
import requests
import gnupg
from pathlib import Path
from typing import Optional, Tuple
from urllib.parse import urlparse
from .exceptions import SecurityError, NetworkError

class SignatureVerifier:
    """镜像签名验证模块"""
    
    def __init__(self):
        self.gpg = gnupg.GPG(
            gnupghome=str(Path.home() / ".gnupg"),
            keyring=os.path.join(os.path.dirname(__file__), "trusted-keys.gpg")
        )
        self._init_keyring()
    
    def _init_keyring(self) -> None:
        """初始化可信密钥环"""
        trusted_keys_path = Path(__file__).parent / "trusted-keys.gpg"
        if trusted_keys_path.exists():
            with open(trusted_keys_path, "rb") as f:
                self.gpg.import_keys(f.read())
    
    def verify_mirror_signature(self, mirror_url: str, sig_url: str) -> Tuple[bool, Optional[str]]:
        """
        验证镜像站签名有效性
        :param mirror_url: 镜像站地址 (e.g. https://mirror.example.com/)
        :param sig_url: 签名文件下载地址
        :return: (验证结果, 密钥指纹)
        """
        # 下载签名文件
        try:
            sig_resp = requests.get(sig_url, timeout=10)
            sig_resp.raise_for_status()
        except requests.RequestException as e:
            raise NetworkError(f"无法下载签名文件: {str(e)}") from e
        
        # 下载镜像站公钥
        key_url = f"{urlparse(mirror_url).scheme}://{urlparse(mirror_url).netloc}/MIRROR-GPG-KEY"
        try:
            key_resp = requests.get(key_url, timeout=10)
            key_resp.raise_for_status()
        except requests.RequestException as e:
            raise NetworkError(f"无法下载公钥: {str(e)}") from e
        
        # 导入公钥
        import_result = self.gpg.import_keys(key_resp.text)
        if not import_result.results:
            raise SecurityError("无效的GPG公钥")
        
        # 验证签名
        verified = self.gpg.verify(sig_resp.content)
        return (verified.valid, verified.fingerprint)

    @staticmethod
    def verify_desktop_file() -> None:
        """验证桌面文件完整性"""
        desktop_path = "/usr/share/applications/mirror-tool.desktop"
        required_fields = {
            "Exec": "/usr/bin/mirror-tool tui",
            "Icon": "mirror-tool",
            "Categories": "System;"
        }
        
        if not os.path.exists(desktop_path):
            raise SecurityError(f"桌面文件缺失: {desktop_path}")
        
        with open(desktop_path, 'r') as f:
            content = f.read()
            
        for field, value in required_fields.items():
            if f"{field}={value}" not in content:
                raise SecurityError(f"桌面文件字段验证失败: {field}={value}")

class SecurityManager:
    """综合安全验证控制器"""
    
    def __init__(self):
        self.verifier = SignatureVerifier()
    
    def full_verify(self) -> None:
        """执行完整安全验证链"""
        checks = [
            self.verifier.verify_desktop_file,
            self._check_binary_permissions,
            # 可扩展其他检查项
        ]
        
        for check in checks:
            check()
    
    @staticmethod
    def _check_binary_permissions() -> None:
        """验证二进制文件权限"""
        bin_path = "/usr/bin/mirror-tool"
        if not os.path.exists(bin_path):
            raise SecurityError(f"主程序未安装: {bin_path}")
        
        st_mode = os.stat(bin_path).st_mode
        if (st_mode & 0o777) != 0o755:
            raise SecurityError(f"文件权限不安全: {oct(st_mode)}")